home *** CD-ROM | disk | FTP | other *** search
/ Aminet 51 / Aminet 51 (2002)(GTI - Schatztruhe)[!][Oct 2002].iso / Aminet / dev / c / minigl.lha / MiniGL / src / texture.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-05-27  |  37.7 KB  |  1,733 lines

  1. /*
  2.  * $Id: texture.c,v 1.1.1.1 2000/04/07 19:44:51 tfrieden Exp $
  3.  *
  4.  * $Date: 2000/04/07 19:44:51 $
  5.  * $Revision: 1.1.1.1 $
  6.  *
  7.  * (C) 1999 by Hyperion
  8.  * All rights reserved
  9.  *
  10.  * This file is part of the MiniGL library project
  11.  * See the file Licence.txt for more details
  12.  *
  13.  */
  14.  
  15. #include "sysinc.h"
  16.  
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #ifdef __VBCC__
  20. #include <string.h> //inlined memcpy
  21. #endif
  22.  
  23.  
  24. static char rcsid[] = "$Id: texture.c,v 1.1.1.1 2000/04/07 19:44:51 tfrieden Exp $";
  25.  
  26.  
  27. #ifndef __PPC__
  28. extern struct ExecBase *SysBase;
  29. #endif
  30.  
  31. void tex_FreeTextures(GLcontext context);
  32. void tex_SetEnv(GLcontext context, GLenum env);
  33. ULONG tex_GLFilter2W3D(GLenum filter);
  34. void tex_SetFilter(GLcontext context, GLenum min, GLenum mag);
  35. void tex_SetWrap(GLcontext context, GLenum wrap_s, GLenum wrap_t);
  36.  
  37. /*
  38. ** Surgeon: support for GL_ALPHA, GL_LUMINANCE and GL_LUMINANCE_ALPHA
  39. ** The support is indirect because GL_ALPHA and GL_LUMINANCE are converted to A4R4G4B4.
  40. ** Funnily A8 and L8 are supported in hardware by Voodoo3 but these formats seem to have some Warp3D related problems. */
  41.  
  42. //NOTE: warp3D has problem with one byte/pixel formats
  43. //#define EIGHTBIT_TEXTURES 1
  44.  
  45. //Formats directly supported by Warp3D:
  46.  
  47. void SHORT4444_4444(GLcontext context, GLubyte *input, UWORD *output, int width, int height);
  48.  
  49. void SHORT565_565(GLcontext context, GLubyte *input, UWORD *output, int width, int height);
  50.  
  51.  
  52. //supported, but not in hardware on voodoo3:
  53.  
  54. void L8A8_L8A8(GLcontext context, GLubyte *input, UWORD *output, int width, int height);
  55.  
  56. #ifdef EIGHTBIT_TEXTURES
  57.  
  58. void EIGHT_EIGHT(GLcontext context, GLubyte *input, UWORD *output, int width, int height);
  59.  
  60. #endif
  61.  
  62.  
  63.  
  64. //conversion routines:
  65.  
  66. void SHORT565_4444(GLcontext context, GLubyte *input, UWORD *output, int width, int height);
  67.  
  68. void SHORT4444_565(GLcontext context, GLubyte *input, UWORD *output, int width, int height);
  69.  
  70. void A8_ARGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height);
  71.  
  72. void L8_ARGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height);
  73.  
  74. void RGBA_RGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height);
  75.  
  76. void RGBA_ARGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height);
  77.  
  78. void RGB_RGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height);
  79.  
  80. void RGB_ARGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height);
  81.  
  82. void RGBA4_ARGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height);
  83.  
  84. ULONG MGLConvert(GLcontext context, const GLvoid *inputp, UWORD *output, int width, int height, GLenum internalformat, GLenum format);
  85.  
  86. static ULONG Allocated_Size = 0;
  87. static ULONG Peak_Size      = 0;
  88.  
  89. void *tex_Alloc(ULONG size)
  90. {
  91.     ULONG *x;
  92.     Allocated_Size += size+4;
  93.     x=(ULONG *)malloc(size+4);
  94.     *x = size;
  95.  
  96.     if (Allocated_Size > Peak_Size) Peak_Size = Allocated_Size;
  97.  
  98.     return x+1;
  99. }
  100.  
  101. void tex_Free(void *chunk)
  102. {
  103.     ULONG *mem = (ULONG *)chunk;
  104.     mem--;
  105.     Allocated_Size -= *mem;
  106.     Allocated_Size -= 4;
  107.     free(mem);
  108. }
  109.  
  110. void tex_Statistic(void)
  111. {
  112. //    printf("Peak Allocation Size: %ld\n", Peak_Size);
  113.     printf("Peak Allocation Size: %lu\n", Peak_Size); //OF
  114.  
  115. }
  116.  
  117. void MGLTexMemStat(GLcontext context, GLint *Current, GLint *Peak)
  118. {
  119.     if (Current) *Current = (GLint)Allocated_Size;
  120.     if (Peak)    *Peak    = (GLint)Peak_Size;
  121. }
  122.  
  123. void GLDeleteTextures(GLcontext context, GLsizei n, const GLuint *textures)
  124. {
  125.     int i;
  126.     for (i=0; i<n; i++)
  127.     {
  128.         int j = *textures++;
  129.         if (context->w3dTexBuffer[j])
  130.         {
  131.             W3D_FreeTexObj(context->w3dContext, context->w3dTexBuffer[j]);
  132.             context->w3dTexBuffer[j] = NULL;
  133.         }
  134.         if (context->w3dTexMemory[j])
  135.         {
  136.             void *x = context->w3dTexMemory[j];
  137.             tex_Free(x);
  138.             context->w3dTexMemory[j] = NULL;
  139.         }
  140.         context->GeneratedTextures[j] = 0;
  141.     }
  142. }
  143.  
  144. void GLGenTextures(GLcontext context, GLsizei n, GLuint *textures)
  145. {
  146.     int i,j;
  147.  
  148.     j = 1;
  149.     for (i=0; i<n; i++)
  150.     {
  151.         // Find a free texture
  152.         while (j < context->TexBufferSize)
  153.         {
  154.             if (context->GeneratedTextures[j] == 0) break;
  155.             j++;
  156.         }
  157.  
  158.         // If we get here, we found one, or there's noting available. Flag an error in that case..
  159.         if (j == context->TexBufferSize)
  160.         {
  161.             GLFlagError(context, j == context->TexBufferSize, GL_INVALID_OPERATION);
  162.             return;
  163.         }
  164.  
  165.         // Insert the texture in the output array, and flag it as used internally
  166.         *textures = j;
  167.         context->GeneratedTextures[j] = 1;
  168.         textures++;
  169.         j++;
  170.     }
  171. }
  172.  
  173.  
  174.  
  175. void tex_FreeTextures(GLcontext context)
  176. {
  177.     int i;
  178.  
  179.     for (i=0; i<context->TexBufferSize; i++)
  180.     {
  181.         if (context->w3dTexBuffer[i])
  182.         {
  183.             W3D_FreeTexObj(context->w3dContext, context->w3dTexBuffer[i]);
  184.         }
  185.  
  186.         if (context->w3dTexMemory[i])
  187.         {
  188.             tex_Free(context->w3dTexMemory[i]);
  189.         }
  190.  
  191.         context->w3dTexBuffer[i] = 0;
  192.         context->w3dTexMemory[i] = 0;
  193.     }
  194.     W3D_FreeAllTexObj(context->w3dContext);
  195. }
  196.  
  197.  
  198. void tex_SetEnv(GLcontext context, GLenum env)
  199. {
  200.     W3D_Texture *tex;
  201.  
  202.     if(context->ActiveTexture == 1)
  203.         return;
  204.  
  205.     if(context->CurTexEnv == env)
  206.         return;
  207.  
  208.     tex = context->w3dTexBuffer[context->CurrentBinding];
  209.  
  210.     if (!tex) return;
  211.  
  212.     context->CurTexEnv = env;
  213.  
  214.     switch(env)
  215.     {
  216.         case GL_MODULATE:   W3D_SetTexEnv(context->w3dContext, tex, W3D_MODULATE, NULL);
  217.                             break;
  218.         case GL_DECAL:      W3D_SetTexEnv(context->w3dContext, tex, W3D_DECAL, NULL);
  219.                             break;
  220.         case GL_REPLACE:    W3D_SetTexEnv(context->w3dContext, tex, W3D_REPLACE, NULL);
  221.                             break;
  222.         default:            break;
  223.     }
  224. }
  225.  
  226. ULONG tex_GLFilter2W3D(GLenum filter)
  227. {
  228.     switch(filter)
  229.     {
  230.         case GL_NEAREST:                return W3D_NEAREST;
  231.         case GL_LINEAR:                 return W3D_LINEAR;
  232.         case GL_NEAREST_MIPMAP_NEAREST: return W3D_NEAREST_MIP_NEAREST;
  233.         case GL_LINEAR_MIPMAP_NEAREST:  return W3D_LINEAR_MIP_NEAREST;
  234.         case GL_NEAREST_MIPMAP_LINEAR:  return W3D_NEAREST_MIP_LINEAR;
  235.         case GL_LINEAR_MIPMAP_LINEAR:   return W3D_LINEAR_MIP_LINEAR;
  236.     }
  237.     return 0;
  238. }
  239.  
  240. void tex_SetFilter(GLcontext context, GLenum min, GLenum mag)
  241. {
  242.     ULONG minf, magf;
  243.     W3D_Texture *tex;
  244.  
  245.     if(context->ActiveTexture)
  246.         tex = context->w3dTexBuffer[context->VirtualBinding];
  247.     else
  248.         tex = context->w3dTexBuffer[context->CurrentBinding];
  249.  
  250.     if (!tex) return;
  251.  
  252.     minf = tex_GLFilter2W3D(min);
  253.     magf = tex_GLFilter2W3D(mag);
  254.  
  255.     W3D_SetFilter(context->w3dContext, tex, minf, magf);
  256. }
  257.  
  258. void tex_SetWrap(GLcontext context, GLenum wrap_s, GLenum wrap_t)
  259. {
  260.     ULONG Ws,Wt;
  261.     W3D_Texture *tex;
  262.  
  263.     if(context->ActiveTexture)
  264.         tex = context->w3dTexBuffer[context->VirtualBinding];
  265.     else
  266.         tex = context->w3dTexBuffer[context->CurrentBinding];
  267.  
  268.     if (!tex) return;
  269.  
  270.     if (wrap_s == GL_REPEAT) Ws = W3D_REPEAT;
  271.                         else Ws = W3D_CLAMP;
  272.     if (wrap_t == GL_REPEAT) Wt = W3D_REPEAT;
  273.                         else Wt = W3D_CLAMP;
  274.  
  275.     W3D_SetWrapMode(context->w3dContext, tex, Ws, Wt, NULL);
  276. }
  277.  
  278. void GLTexEnvi(GLcontext context, GLenum target, GLenum pname, GLint param)
  279. {
  280.    //LOG(2, glTexEnvi, "%d %d", pname, param);
  281.  
  282.     //ignore unit 1 env until mglDrawMultitexBuffer
  283.  
  284.     if(context->ActiveTexture == 1)
  285.         return;
  286.  
  287.        context->TexEnv[0] = (GLenum)param;
  288.  
  289.        tex_SetEnv(context, param);
  290. }
  291.  
  292. void GLTexParameteri(GLcontext context, GLenum target, GLenum pname, GLint param)
  293. {
  294.     GLenum min, mag;
  295.     GLenum wraps, wrapt;
  296.     //LOG(2, glTexParameteri, "%d %d %d", target, pname, param);
  297.     switch(pname)
  298.     {
  299.         case GL_TEXTURE_MIN_FILTER:
  300.             mag = context->MagFilter;
  301.             tex_SetFilter(context, mag, (GLenum)param);
  302.             context->MinFilter = (GLenum)param;
  303.             break;
  304.  
  305.         case GL_TEXTURE_MAG_FILTER:
  306.             min = context->MinFilter;
  307.             tex_SetFilter(context, (GLenum)param, min);
  308.             context->MagFilter = (GLenum)param;
  309.             break;
  310.  
  311.         case GL_TEXTURE_WRAP_S:
  312.             wrapt = context->WrapT;
  313.             tex_SetWrap(context, (GLenum)param, wrapt);
  314.             context->WrapS = (GLenum)param;
  315.             break;
  316.  
  317.         case GL_TEXTURE_WRAP_T:
  318.             wraps = context->WrapS;
  319.             tex_SetWrap(context, wraps, (GLenum)param);
  320.             context->WrapT = (GLenum)param;
  321.             break;
  322.         default:
  323.             GLFlagError(context, 1, GL_INVALID_ENUM);
  324.     }
  325. }
  326.  
  327. void GLPixelStorei(GLcontext context, GLenum pname, GLint param)
  328. {
  329.     switch(pname)
  330.     {
  331.         case GL_PACK_ALIGNMENT:
  332.             context->PackAlign = param;
  333.             break;
  334.  
  335.         case GL_UNPACK_ALIGNMENT:
  336.             context->UnpackAlign = param;
  337.             break;
  338.  
  339.       case GL_UNPACK_ROW_LENGTH:
  340.      context->CurUnpackRowLength = param ;
  341.      break ;
  342.  
  343.       case GL_UNPACK_SKIP_PIXELS:
  344.      context->CurUnpackSkipPixels = param ;
  345.      break ;
  346.  
  347.       case GL_UNPACK_SKIP_ROWS:
  348.      context->CurUnpackSkipRows = param ;
  349.      break ;
  350.  
  351.         default:
  352.             // Others here
  353.             break;
  354.     }
  355. }
  356.  
  357. void GLBindTexture(GLcontext context, GLenum target, GLuint texture)
  358. {
  359.    int active;
  360.  
  361.     //LOG(2, glBindTexture, "%d %d", target, texture);
  362.     GLFlagError(context, target != GL_TEXTURE_2D, GL_INVALID_ENUM);
  363.  
  364.    active = context->ActiveTexture;
  365.  
  366.  
  367.    if(active)
  368.    {
  369.     context->VirtualBinding = texture;
  370.  
  371.     if (context->w3dTexBuffer[context->VirtualBinding] == NULL)
  372.     {   // Set to default for unbound objects
  373.         context->MinFilter = GL_NEAREST;
  374.         context->MagFilter = GL_NEAREST;
  375.         context->WrapS     = GL_REPEAT;
  376.         context->WrapT     = GL_REPEAT;
  377.     }
  378.    }
  379.    else
  380.    {
  381.     context->CurrentBinding = texture;
  382.  
  383.     if (context->w3dTexBuffer[context->CurrentBinding] == NULL)
  384.     {   // Set to default for unbound objects
  385.         context->TexEnv[0] = GL_MODULATE;
  386.         context->MinFilter = GL_NEAREST;
  387.         context->MagFilter = GL_NEAREST;
  388.         context->WrapS     = GL_REPEAT;
  389.         context->WrapT     = GL_REPEAT;
  390.     }
  391.    }
  392. }
  393.  
  394.  
  395. /*
  396. ** There are two possible output formats:
  397. ** - RGB
  398. ** - RGBA
  399. **
  400. ** There are two possible input formats:
  401. ** - RGB
  402. ** - RGBA
  403. **
  404. ** Thus there must be four conversion routines, since the
  405. ** routine must be able to add or remove the alpha component
  406. **
  407. ** The following set of routines assumes that input is always given as
  408. ** a stream of GL_UNSIGNED_BYTE with either three or four components.
  409. **
  410. ** ROOM FOR IMPROVMENT
  411. ** These routines assume way too much to be considered anything else but
  412. ** special cases. The whole texture stuff should be reworked to include
  413. ** possible convertion routines for all kinds of textures. This could, of
  414. ** course, be left to Warp3D, but this would mean there has to be two sets
  415. ** of textures in memory, which is clearly too much. Perhaps we should
  416. ** change the behaviour of Warp3D in this point - room for discussion.
  417. */
  418.  
  419. #define CORRECT_ALIGN \
  420.         if ((int)input % context->PackAlign) \
  421.         { \
  422.             input += context->PackAlign - ((int)input % context->PackAlign);\
  423.         } \
  424.  
  425.  
  426. #define SETUP_LOOP(x) \
  427.     GLubyte *oldInput;                          \
  428.     int realWidth = width*x;                    \
  429.     if (context->CurUnpackRowLength > 0)        \
  430.         realWidth = context->CurUnpackRowLength*x;
  431.  
  432.  
  433. #define SETUP_LOOP_SHORT(x)                         \
  434.     UWORD *oldInput;                            \
  435.     int realWidth = width;                      \
  436.     if (context->CurUnpackRowLength > 0)        \
  437.         realWidth = context->CurUnpackRowLength;
  438.  
  439. #define SETUP_LOOP_LONG                         \
  440.     ULONG *oldInput;                            \
  441.     int realWidth = width;                      \
  442.     if (context->CurUnpackRowLength > 0)        \
  443.         realWidth = context->CurUnpackRowLength;
  444.  
  445.  
  446. #define CORRECT_ALIGN_SHORT \
  447.         if ((int)input % context->PackAlign) \
  448.         { \
  449.             input += ((context->PackAlign - ((int)input % context->PackAlign))>>1);\
  450.         } \
  451.  
  452. #define CORRECT_ALIGN_LONG \
  453.         if ((int)input % context->PackAlign) \
  454.         { \
  455.             input += ((context->PackAlign - ((int)input % context->PackAlign))>>2);\
  456.         } \
  457.  
  458.  
  459. #define START_LOOP \
  460.     oldInput = input;
  461.  
  462. #define NEXT_LOOP       \
  463.     input = oldInput + realWidth;
  464.  
  465.  
  466. #define ARGBFORM(a,r,g,b) \
  467.     ( (UWORD)(((( a & 0xf0 ) << 8)  \
  468.     |(( r & 0xf0 ) << 4)  \
  469.     |(( g & 0xf0 )     )  \
  470.     |(( b & 0xf0 ) >> 4))) )
  471.  
  472. /*
  473. #define RGBFORM(r,g,b) \
  474.     ( (UWORD)(0x8000 | ((r & 0xF8) << 7) \
  475.                | ((g & 0xF8) << 2) \
  476.                | ((b & 0xF8) >> 3)) )
  477.  
  478.  
  479. #define REDBYTE(rgb)    (((UWORD)rgb & 0x7C00) >> 7)
  480. #define GREENBYTE(rgb)  (((UWORD)rgb & 0x03E0) >> 2)
  481. #define BLUEBYTE(rgb)   (((UWORD)rgb & 0x001F) << 3)
  482. #define RGB_GET(i) ((UBYTE *)(context->PaletteData)+3*i)
  483. #define ARGB_GET(i) ((UBYTE *)(context->PaletteData)+4*i)
  484. */
  485.  
  486. #define RGBFORM(r,g,b) \
  487.     ( (UWORD)(((r & 0xF8) << 8) \
  488.           | ((g & 0xFC) << 3) \
  489.           | ((b & 0xF8) >> 3)) )
  490.  
  491.  
  492. #define REDBYTE(rgb)        (((UWORD)rgb & 0xF800) >> 8)
  493. #define GREENBYTE(rgb)      (((UWORD)rgb & 0x07E0) >> 3)
  494. #define BLUEBYTE(rgb)       (((UWORD)rgb & 0x001F) << 3)
  495. #define REDBYTEA(rgba)      (((UWORD)rgba & 0x0f00) >> 4)
  496. #define GREENBYTEA(rgba)    (((UWORD)rgba & 0x00f0))
  497. #define BLUEBYTEA(rgba)     (((UWORD)rgba & 0x000f) << 4)
  498. #define ALPHABYTEA(rgba)    (((UWORD)rgba & 0xf000) >> 8)
  499. #define RGB_GET(i) ((UBYTE *)(context->PaletteData)+3*i)
  500. #define ARGB_GET(i) ((UBYTE *)(context->PaletteData)+4*i)
  501.  
  502.  
  503. /*
  504. ** This function converts a non-alpha texture buffer into a
  505. ** alpha'ed texture buffer. This is used in case additive blending
  506. ** was selected but the texture does not have alpha, and additive blending
  507. ** is not
  508. */
  509.  
  510. void tex_AddAlpha(UWORD *output, int width, int height)
  511. {
  512.     int size;
  513.     UBYTE r,g,b,a;
  514.     UWORD x;
  515.     ULONG a_tmp;
  516.     size = width*height;
  517.  
  518.     while (size)
  519.     {
  520.     x=*output;
  521.     
  522.     r = REDBYTE(x);
  523.     g = GREENBYTE(x);
  524.     b = BLUEBYTE(x);
  525.  
  526.     //a=(r+g+b)/3;
  527.  
  528.     a=(r>g)?r:g;
  529.     a=(a>b)?a:b;
  530.  
  531.  
  532.     // These should emulate additive blending, so ensure it's in some appropriate range
  533.  
  534. /*
  535.     a *= 0.8f;
  536. */
  537.     a_tmp = a;
  538.     a_tmp <<= 3;
  539.     a_tmp /= 10;
  540.     a = a_tmp;
  541.  
  542.     *output = ARGBFORM(a,r,g,b);
  543.     output++; size--;
  544.     }
  545. }
  546.  
  547.  
  548. /*
  549. ** Convert the currently bound texture to a format that has an alpha channel.
  550. ** Also sets the texture parameters according to the current settings.
  551. */
  552.  
  553. void tex_ConvertTexture(GLcontext context)
  554. {
  555.     W3D_Texture *newtex;
  556.     struct TagItem AllocTags[20];
  557.     W3D_Texture *oldtex = context->w3dTexBuffer[context->CurrentBinding];
  558.     UWORD *output = (UWORD *)context->w3dTexMemory[context->CurrentBinding];
  559.  
  560.     if (!oldtex) return;
  561.     if (oldtex->texfmtsrc == context->w3dAlphaFormat) return;
  562.  
  563.     tex_AddAlpha(output, oldtex->texwidth, oldtex->texheight);
  564.  
  565.     AllocTags[0].ti_Tag  = W3D_ATO_IMAGE;
  566.     AllocTags[0].ti_Data = (ULONG)context->w3dTexMemory[context->CurrentBinding];
  567.  
  568.     AllocTags[1].ti_Tag  = W3D_ATO_FORMAT;
  569.     AllocTags[1].ti_Data = context->w3dAlphaFormat;
  570.  
  571.     AllocTags[2].ti_Tag  = W3D_ATO_WIDTH;
  572.     AllocTags[2].ti_Data = oldtex->texwidth;
  573.  
  574.     AllocTags[3].ti_Tag  = W3D_ATO_HEIGHT;
  575.     AllocTags[3].ti_Data = oldtex->texheight;
  576.  
  577.     AllocTags[4].ti_Tag  = TAG_DONE;
  578.     AllocTags[4].ti_Data = 0;
  579.  
  580.     newtex = W3D_AllocTexObj(context->w3dContext, NULL, AllocTags);
  581.     if (!newtex)    return;
  582.     
  583.     W3D_FreeTexObj(context->w3dContext, oldtex);
  584.     context->w3dTexBuffer[context->CurrentBinding] = newtex;
  585.  
  586.     tex_SetEnv(context, context->TexEnv[0]);
  587.  
  588.     tex_SetFilter(context, context->MinFilter, context->MagFilter);
  589.  
  590.     tex_SetWrap(context, context->WrapS, context->WrapT);
  591. }
  592.  
  593.  
  594. //These formats need no conversion:
  595.  
  596. void EIGHT_EIGHT (GLcontext context, GLubyte *input, UWORD *output, int width, int height)
  597. {
  598.     int i,j;
  599.     UBYTE *in = (UBYTE*)input;
  600.     UBYTE *out = (UBYTE*)output;
  601.  
  602.     for (i=0; i<height; i++)
  603.     {
  604.         for (j=0; j<width; j++)
  605.         {
  606.             *out++ = *in++;
  607.         }
  608.         CORRECT_ALIGN
  609.     }
  610. }
  611.  
  612. void L8A8_L8A8(GLcontext context, GLubyte *input, UWORD *output, int width, int height)
  613. {
  614.     int i,j;
  615.  
  616. //assume a width divisible by 2 for faster copy
  617.  
  618.     UWORD *in = (UWORD*)input;
  619.     UWORD *out = (UWORD*)output;
  620.  
  621.     for (i=0; i<height;i++)
  622.     {
  623.         for (j=0; j<width; j++)
  624.         {
  625.             *out++ = *in++;
  626.         }
  627.         CORRECT_ALIGN
  628.     }
  629. }
  630.  
  631. void SHORT565_565(GLcontext context, GLubyte *input, UWORD *output, int width, int height)
  632. {
  633.     int i,j;
  634.  
  635. //assume a width divisible by 2 for faster copy
  636.  
  637.     UWORD *in = (UWORD*)input;
  638.     UWORD *out = (UWORD*)output;
  639.  
  640.     for (i = 0; i < height; i++)
  641.     {
  642.         for (j = 0; j < width; j++)
  643.         {
  644.             *out++ = *in++;
  645.         }
  646.         CORRECT_ALIGN
  647.     }
  648. }
  649.  
  650. void SHORT4444_4444(GLcontext context, GLubyte *input, UWORD *output, int width, int height)
  651. {
  652.     int i,j;
  653.  
  654. //assume a width divisible by 2 for faster copy
  655.  
  656.     UWORD *in = (UWORD*)input;
  657.     UWORD *out = (UWORD*)output;
  658.  
  659.     for (i = 0; i < height; i++)
  660.     {
  661.         for (j = 0; j < width; j++)
  662.         {
  663.             *out++ = *in++;
  664.         }
  665.         CORRECT_ALIGN
  666.     }
  667. }
  668.  
  669. //These formats need conversion:
  670.  
  671. #if 1
  672.  
  673. void A8_ARGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height)
  674. {
  675.     int i,j;
  676.     GLubyte a;
  677.  
  678.     for (i=0; i<height;i++)
  679.     {
  680.         for (j=0; j<width; j++)
  681.         {
  682.             a = *input++;
  683.             *output++ = ( ((UWORD)a & 0xF0) << 8) | 0x0FFF;
  684.         }
  685.         CORRECT_ALIGN
  686.     }
  687. }
  688.  
  689. void L8_ARGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height)
  690. {
  691.     int i,j;
  692.     GLubyte la,lb,lc;
  693.  
  694.     for (i=0; i<height;i++)
  695.     {
  696.         for (j=0; j<width; j++)
  697.         {
  698.             la = lb = lc = *input++;
  699.             *output++ = ARGBFORM(0xff, la, lb, lc);
  700.         }
  701.         CORRECT_ALIGN
  702.     }
  703. }
  704.  
  705. #endif
  706.  
  707. void RGBA_RGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height)
  708. {
  709.     int i,j;
  710.     UBYTE r,g,b,a;
  711.  
  712.     for (i=0; i<height;i++)
  713.     {
  714.         for (j=0; j<width; j++)
  715.         {
  716.             r=*input++;
  717.             g=*input++;
  718.             b=*input++;
  719.             a=*input++;
  720.             *output++ = RGBFORM(r,g,b);
  721.         }
  722.         CORRECT_ALIGN
  723.     }
  724. }
  725.  
  726.  
  727. void RGBA_ARGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height)
  728. {
  729.     int i,j;
  730.     UBYTE r,g,b,a;
  731.  
  732.     for (i=0; i<height;i++)
  733.     {
  734.         for (j=0; j<width; j++)
  735.         {
  736.             r=*input++;
  737.             g=*input++;
  738.             b=*input++;
  739.             a=*input++;
  740.             *output++ = ARGBFORM(a,r,g,b);
  741.         }
  742.         CORRECT_ALIGN
  743.     }
  744. }
  745.  
  746. void RGB_RGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height)
  747. {
  748.     int i,j;
  749.     UBYTE r,g,b;
  750.  
  751.     for (i=0; i<height;i++)
  752.     {
  753.         for (j=0; j<width; j++)
  754.         {
  755.             r=*input++;
  756.             g=*input++;
  757.             b=*input++;
  758.             *output++ = RGBFORM(r,g,b);
  759.         }
  760.         CORRECT_ALIGN
  761.     }
  762. }
  763.  
  764. void RGB_ARGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height)
  765. {
  766.     int i,j;
  767.     UBYTE r,g,b;
  768.  
  769.     for (i=0; i<height;i++)
  770.     {
  771.         for (j=0; j<width; j++)
  772.         {
  773.             r=*input++;
  774.             g=*input++;
  775.             b=*input++;
  776.             *output++ = ARGBFORM(0xff,r,g,b);
  777.         }
  778.         CORRECT_ALIGN
  779.     }
  780. }
  781.  
  782. void SHORT4444_565(GLcontext context, GLubyte *input, UWORD *output, int width, int height)
  783. {
  784.     int i,j;
  785.     UBYTE r,g,b;
  786.     UWORD *in = (UWORD *)input;
  787.  
  788.     for (i = 0; i < height; i++)
  789.     {
  790.         for (j = 0; j < width; j++)
  791.         {
  792.             r = REDBYTEA(*in);
  793.             g = GREENBYTEA(*in);
  794.             b = BLUEBYTEA(*in);
  795.             *output++ = RGBFORM(r, g, b);
  796.             in++;
  797.         }
  798.         CORRECT_ALIGN
  799.     }
  800. }
  801.  
  802. void SHORT565_4444(GLcontext context, GLubyte *input, UWORD *output, int width, int height)
  803. {
  804.     int i,j;
  805.     UBYTE r,g,b;
  806.  
  807.     UWORD *in = (UWORD *)input;
  808.  
  809.     for (i = 0; i < height; i++)
  810.     {
  811.         for (j = 0; j < width; j++)
  812.         {
  813.             r = REDBYTE(*in);
  814.             g = GREENBYTE(*in);
  815.             b = BLUEBYTE(*in);
  816.             *output++ = ARGBFORM(0xff, r, g, b);
  817.             in++;
  818.         }
  819.         CORRECT_ALIGN
  820.     }
  821. }
  822.  
  823. void RGBA4_ARGB (GLcontext context, GLubyte *input, UWORD *output, int width, int height)
  824. {
  825.     int i,j;
  826.     UBYTE r,g,b,a;
  827.  
  828.     UWORD *in = (UWORD *)input;
  829.  
  830.     for (i = 0; i < height; i++)
  831.     {
  832.         for (j = 0; j < width; j++)
  833.         {
  834.             r = ((*in)&0xf000) >> 8;
  835.             g = ((*in)&0x0f00) >> 4;
  836.             b = ((*in)&0x00f0);
  837.             a = ((*in)&0x000f) << 4;
  838.             *output++ = ARGBFORM(a, r, g, b);
  839.             in++;
  840.         }
  841.         CORRECT_ALIGN
  842.     }
  843. }
  844.  
  845. void INDEX_RGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height)
  846. {
  847.     int i,j;
  848.     UBYTE ind;
  849.     UBYTE r,g,b;
  850.  
  851.     if (context->PaletteFormat == GL_RGB)
  852.     {
  853.         for (i=0; i<height; i++)
  854.         {
  855.             for (j=0; j<width; j++)
  856.             {
  857.                 ind = *input++;
  858.                 r = *RGB_GET(ind);
  859.                 g = *(RGB_GET(ind)+1);
  860.                 b = *(RGB_GET(ind)+2);
  861.                 *output++ = RGBFORM(r,g,b);
  862.             }
  863.             CORRECT_ALIGN
  864.         }
  865.     }
  866.     else
  867.     {
  868.         for (i=0; i<height; i++)
  869.         {
  870.             for (j=0; j<width; j++)
  871.             {
  872.                 ind = *input++;
  873.                 r = *RGB_GET(ind);
  874.                 g = *(ARGB_GET(ind)+1);
  875.                 b = *(ARGB_GET(ind)+2);
  876.                 *output++ = RGBFORM(r,g,b);
  877.             }
  878.             CORRECT_ALIGN
  879.         }
  880.  
  881.     }
  882. }
  883.  
  884. void INDEX_ARGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height)
  885. {
  886.     int i,j;
  887.     UBYTE ind;
  888.     UBYTE r,g,b,a;
  889.  
  890.     if (context->PaletteFormat == GL_RGB)
  891.     {
  892.         for (i=0; i<height; i++)
  893.         {
  894.             for (j=0; j<width; j++)
  895.             {
  896.                 ind = *input++;
  897.                 r = *RGB_GET(ind);
  898.                 g = *(RGB_GET(ind)+1);
  899.                 b = *(RGB_GET(ind)+2);
  900.                 *output++ = ARGBFORM(0xff,r,g,b);
  901.             }
  902.             CORRECT_ALIGN
  903.         }
  904.     }
  905.     else
  906.     {
  907.         for (i=0; i<height; i++)
  908.         {
  909.             for (j=0; j<width; j++)
  910.             {
  911.                 ind = *input++;
  912.                 r = *RGB_GET(ind);
  913.                 g = *(ARGB_GET(ind)+1);
  914.                 b = *(ARGB_GET(ind)+2);
  915.                 a = *(ARGB_GET(ind)+3);
  916.                 *output++ = ARGBFORM(a,r,g,b);
  917.             }
  918.             CORRECT_ALIGN
  919.         }
  920.  
  921.     }
  922. }
  923.  
  924.  
  925.  
  926. ULONG MGLConvert(GLcontext context, const GLvoid *inputp, UWORD *output, int width, int height, GLenum internalformat, GLenum format)
  927. {
  928.     GLvoid *input = (GLvoid *)inputp;
  929.  
  930.     switch(internalformat) // The format the texture should have
  931.     {
  932.         case GL_ALPHA: //eq 1
  933.             switch(format)
  934.             {
  935.                 case GL_ALPHA:
  936.                 #ifdef EIGHTBIT_TEXTURES
  937.                     EIGHT_EIGHT(context, (GLubyte *)input, output, width, height);
  938.                     return W3D_A8;
  939.                 #else
  940.                     A8_ARGB(context, (GLubyte *)input, output, width, height);
  941.                     return context->w3dAlphaFormat;
  942.  
  943.                 #endif
  944.             }
  945.             break;
  946.  
  947.         case GL_LUMINANCE:
  948.             switch(format) // the format of the pixel (input) data
  949.             {
  950.                 case GL_LUMINANCE:
  951.                 #ifdef EIGHTBIT_TEXTURES
  952.                     EIGHT_EIGHT(context, (GLubyte *)input, output, width, height);
  953.                     return W3D_L8;
  954.                 #else
  955.                     L8_ARGB(context, (GLubyte *)input, output, width, height);
  956.                     return context->w3dAlphaFormat;
  957.                 #endif
  958.             }
  959.             break;
  960.  
  961.         case GL_LUMINANCE_ALPHA:
  962.             switch(format)
  963.             {
  964.                 case GL_LUMINANCE_ALPHA:
  965.                     L8A8_L8A8(context, (GLubyte *)input, output, width, height);
  966.                     return W3D_L8A8;
  967.             }
  968.             break;
  969.  
  970.         case 3:
  971.         case GL_RGB:
  972.             switch(format)
  973.             {
  974.                 case GL_RGB:
  975.                     RGB_RGB(context, (GLubyte *)input, output, width, height);
  976.                     return context->w3dFormat;
  977.                 case GL_RGBA:
  978.                     RGBA_RGB(context, (GLubyte *)input, output, width, height);
  979.                     return context->w3dFormat;
  980.                 case GL_COLOR_INDEX:
  981.                     INDEX_RGB(context, (GLubyte *)input, output, width, height);
  982.                     return context->w3dFormat;
  983.                 case MGL_UNSIGNED_SHORT_5_6_5:
  984.                     SHORT565_565(context, (GLubyte *)input, output, width, height);
  985.                     return context->w3dFormat;
  986.                 case MGL_UNSIGNED_SHORT_4_4_4_4:
  987.                     SHORT4444_565(context, (GLubyte *)input, output, width, height);
  988.                     return context->w3dFormat;
  989.  
  990.             }
  991.             break;
  992.  
  993.         case 4:
  994.         case GL_RGBA:
  995.             switch(format)
  996.             {
  997.                 case GL_RGB:
  998.                     RGB_ARGB(context, (GLubyte *)input, output, width, height);
  999.                     return context->w3dAlphaFormat;
  1000.                 case GL_RGBA:
  1001.                     RGBA_ARGB(context, (GLubyte *)input, output, width, height);
  1002.                     return context->w3dAlphaFormat;
  1003.                 case GL_COLOR_INDEX:
  1004.                     INDEX_ARGB(context, (GLubyte *)input, output, width, height);
  1005.                     return context->w3dAlphaFormat;
  1006.                 case MGL_UNSIGNED_SHORT_5_6_5:
  1007.                     SHORT565_4444(context, (GLubyte *)input, output, width, height);
  1008.                     return context->w3dAlphaFormat;
  1009.                 case MGL_UNSIGNED_SHORT_4_4_4_4:
  1010.                     SHORT4444_4444(context, (GLubyte *)input, output, width, height);
  1011.                     return context->w3dAlphaFormat;
  1012.             }
  1013.             break;
  1014.  
  1015.             case MGL_UNSIGNED_SHORT_5_6_5:
  1016.             switch(format)
  1017.             {
  1018.                 case MGL_UNSIGNED_SHORT_5_6_5:
  1019.                 SHORT565_565(context, (GLubyte *)input, output, width, height);
  1020.                 return context->w3dFormat;
  1021.             }
  1022.             break;
  1023.  
  1024.         case MGL_UNSIGNED_SHORT_4_4_4_4:
  1025.             switch(format)
  1026.             {
  1027.                 case MGL_UNSIGNED_SHORT_4_4_4_4:
  1028.                 SHORT4444_4444(context, (GLubyte *)input, output, width, height);
  1029.                 return context->w3dAlphaFormat;
  1030.             }
  1031.             break;
  1032.     }
  1033. }
  1034.  
  1035. void GLTexImage2DNoMIP(GLcontext context, GLenum gltarget, GLint level,
  1036.     GLint internalformat, GLsizei width, GLsizei height, GLint border,
  1037.     GLenum format, GLenum type, const GLvoid *pixels);
  1038.  
  1039.  
  1040. #ifndef __PPC__
  1041.  
  1042. void UpdateTexImage(W3D_Context *context, W3D_Texture *texture, void *image, int level, ULONG *pal)
  1043. {
  1044.     W3D_UpdateTexImage(context, texture, image, level, pal);
  1045. }
  1046.  
  1047. #endif
  1048.  
  1049. void GLTexImage2D(GLcontext context, GLenum gltarget, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
  1050. {
  1051.     int current;
  1052.     ULONG w,h;
  1053.     ULONG targetsize;
  1054.     ULONG error;
  1055.     UBYTE *target;
  1056.     int i,iw,ih;
  1057.     void *miparray[16];
  1058.     ULONG useFormat;
  1059.     ULONG BytesPerTexel;
  1060.     struct TagItem AllocTags[20];
  1061.  
  1062.  
  1063.     if(context->ActiveTexture)
  1064.         current = context->VirtualBinding;
  1065.     else
  1066.         current = context->CurrentBinding;
  1067.  
  1068. #ifdef EIGHTBIT_TEXTURES
  1069.     if(format == GL_ALPHA || format == GL_LUMINANCE)
  1070.         BytesPerTexel = 1;
  1071.     else
  1072. #endif
  1073.         BytesPerTexel = context->w3dBytesPerTexel;
  1074.  
  1075.  
  1076.  
  1077.     if (context->NoMipMapping == GL_TRUE)
  1078.     {
  1079.         GLTexImage2DNoMIP(context, gltarget, level, internalformat, width,
  1080.             height, border, format, type, pixels);
  1081.         return;
  1082.     }
  1083.  
  1084.     GLFlagError(context, type != GL_UNSIGNED_BYTE && type != MGL_UNSIGNED_SHORT_5_6_5 && type != MGL_UNSIGNED_SHORT_4_4_4_4, GL_INVALID_OPERATION);
  1085.     GLFlagError(context, gltarget != GL_TEXTURE_2D, GL_INVALID_ENUM);
  1086.  
  1087.     if (type == MGL_UNSIGNED_SHORT_5_6_5 || type == MGL_UNSIGNED_SHORT_4_4_4_4)
  1088.         format = type;
  1089.  
  1090.  
  1091.     /*
  1092.     ** We will use width and height only when the mipmap level
  1093.     ** is really 0. Otherwise, we need to upscale the values
  1094.     ** according to the level.
  1095.     **
  1096.     ** Note this will most likely be difficult with non-square
  1097.     ** textures, as the first side to reach one will remain
  1098.     ** there. For example, consider the sequence
  1099.     ** 8x4, 4x2, 2x1, 1x1
  1100.     **  0     1   2    3
  1101.     ** If the 1x1 mipmap is given, upscaling will yield 8x8, not 8x4
  1102.     */
  1103.  
  1104.     w=(ULONG)width;
  1105.     h=(ULONG)height;
  1106.     if (level)
  1107.     {
  1108.         int i=level;
  1109.         while (i)
  1110.         {
  1111.             w*=2; h*=2; i--;
  1112.         }
  1113.     }
  1114.  
  1115.     if (context->w3dTexBuffer[current] == NULL)
  1116.     {
  1117.         /*
  1118.         ** Create a new texture object
  1119.         ** Get the memory
  1120.         */
  1121.  
  1122.         targetsize = (w * h * BytesPerTexel * 4) / 3;
  1123.         if (context->w3dTexMemory[current])
  1124.             tex_Free(context->w3dTexMemory[current]);
  1125.         context->w3dTexMemory[current] = (GLubyte *)tex_Alloc(targetsize);
  1126.         if (!context->w3dTexMemory[current])
  1127.             return;
  1128.     }
  1129.  
  1130.     /*
  1131.     ** Find the starting address for the given mipmap level in the
  1132.     ** texture memory area
  1133.     */
  1134.  
  1135.     target = context->w3dTexMemory[current];
  1136.     i = level;
  1137.     iw = w; ih=h;
  1138.  
  1139.     while (i)
  1140.     {
  1141.         target += iw * ih * BytesPerTexel;
  1142.         i      -- ;
  1143.         if (iw>1) iw/=2;
  1144.         if (ih>1) ih/=2;
  1145.     }
  1146.  
  1147.     /*
  1148.     ** Convert the data to the target address
  1149.     */
  1150.  
  1151.     useFormat = MGLConvert(context, pixels, (UWORD *)target, width, height, internalformat, format);
  1152.  
  1153.     /*
  1154.     ** Create a new W3D_Texture if none was present, using the converted
  1155.     ** data.
  1156.     ** Otherwise, call W3D_UpdateTexImage
  1157.     */
  1158.  
  1159.     if (context->w3dTexBuffer[current] == NULL)
  1160.     {
  1161.         i=0;
  1162.         iw=w;
  1163.         ih=h;
  1164.         target = context->w3dTexMemory[current];
  1165.  
  1166.         while (1)
  1167.         {
  1168.             miparray[i++] = target;
  1169.             if (iw == 1 && ih == 1) break;
  1170.  
  1171.             target += iw * ih * BytesPerTexel;
  1172.             if (iw > 1)     iw     /= 2;
  1173.             if (ih > 1)     ih     /= 2;
  1174.         }
  1175.  
  1176.         AllocTags[0].ti_Tag  = W3D_ATO_IMAGE;
  1177.         AllocTags[0].ti_Data = (ULONG)context->w3dTexMemory[current];
  1178.  
  1179.         AllocTags[1].ti_Tag  = W3D_ATO_FORMAT;
  1180.         AllocTags[1].ti_Data = useFormat;
  1181.  
  1182.         AllocTags[2].ti_Tag  = W3D_ATO_WIDTH;
  1183.         AllocTags[2].ti_Data = w;
  1184.  
  1185.         AllocTags[3].ti_Tag  = W3D_ATO_HEIGHT;
  1186.         AllocTags[3].ti_Data = h;
  1187.  
  1188.         AllocTags[4].ti_Tag  = W3D_ATO_MIPMAP;
  1189.         AllocTags[4].ti_Data = 0;
  1190.  
  1191.         AllocTags[5].ti_Tag  = W3D_ATO_MIPMAPPTRS;
  1192.         AllocTags[5].ti_Data = (ULONG)miparray;
  1193.  
  1194.         AllocTags[6].ti_Tag  = TAG_DONE;
  1195.         AllocTags[6].ti_Data = 0;
  1196.  
  1197.         context->w3dTexBuffer[current] = W3D_AllocTexObj(context->w3dContext, &error, AllocTags);
  1198.  
  1199.         if (context->w3dTexBuffer[current] == NULL || error != W3D_SUCCESS) return;
  1200.  
  1201.         /*
  1202.         ** Set the appropriate wrap modes, texture env, and filters
  1203.         */
  1204.         tex_SetWrap(context, context->WrapS, context->WrapT);
  1205.         tex_SetFilter(context, context->MinFilter, context->MagFilter);
  1206.         tex_SetEnv(context, context->TexEnv[0]);
  1207.  
  1208.     }
  1209.  
  1210. #ifndef __PPC__
  1211.         UpdateTexImage(context->w3dContext, context->w3dTexBuffer[current],
  1212.             target, level, NULL);
  1213. #else
  1214.         W3D_UpdateTexImage(context->w3dContext, context->w3dTexBuffer[current],
  1215.             target, level, NULL);
  1216. #endif
  1217. }
  1218.  
  1219. void GLTexImage2DNoMIP(GLcontext context, GLenum gltarget, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
  1220. {
  1221.     int current;
  1222.     ULONG w,h;
  1223.     ULONG targetsize;
  1224.     ULONG error;
  1225.     UBYTE *target;
  1226.     ULONG useFormat;
  1227.     ULONG BytesPerTexel;
  1228.     struct TagItem AllocTags[20];
  1229.  
  1230.  
  1231.     if(context->ActiveTexture)
  1232.         current = context->VirtualBinding;
  1233.     else
  1234.         current = context->CurrentBinding;
  1235.  
  1236. #ifdef EIGHTBIT_TEXTURES
  1237.     if(format == GL_ALPHA || format == GL_LUMINANCE)
  1238.         BytesPerTexel = 1;
  1239.     else
  1240. #endif
  1241.         BytesPerTexel = context->w3dBytesPerTexel;
  1242.  
  1243.  
  1244.     //LOG(3, glTexImage2DNoMIP, "target = %d level=%d, size=%d×%d", gltarget, level, width, height);
  1245.     GLFlagError(context, type != GL_UNSIGNED_BYTE && type != MGL_UNSIGNED_SHORT_5_6_5 && type != MGL_UNSIGNED_SHORT_4_4_4_4, GL_INVALID_OPERATION);
  1246.     GLFlagError(context, gltarget != GL_TEXTURE_2D, GL_INVALID_ENUM);
  1247.  
  1248.     if (type == MGL_UNSIGNED_SHORT_5_6_5 || type == MGL_UNSIGNED_SHORT_4_4_4_4)
  1249.     {
  1250.         format = type;
  1251. //            kprintf("Texture of MGL_UNSIGNED_SHORT_5_6_5, target = %d, level = %d, size %d×%d\n",
  1252. //                        gltarget, level, width, height);
  1253.     }
  1254.  
  1255.     if (level != 0) return;
  1256.  
  1257.     w=(ULONG)width;
  1258.     h=(ULONG)height;
  1259.  
  1260.     if (context->w3dTexBuffer[current] == NULL)
  1261.     {
  1262.     /*
  1263.     ** Create a new texture object
  1264.     ** Get the memory
  1265.     */
  1266.  
  1267.     targetsize = (w * h * BytesPerTexel);
  1268.  
  1269.     if (context->w3dTexMemory[current])
  1270.         tex_Free(context->w3dTexMemory[current]);
  1271.     context->w3dTexMemory[current] = (GLubyte *)tex_Alloc(targetsize);
  1272.     if (!context->w3dTexMemory[current])
  1273.         return;
  1274.     }
  1275.  
  1276.     target = context->w3dTexMemory[current];
  1277.  
  1278.     /*
  1279.     ** Convert the data to the target address
  1280.     */
  1281.     useFormat = MGLConvert(context, pixels, (UWORD *)target, width, height, internalformat, format);
  1282.  
  1283.     /*
  1284.     ** Create a new W3D_Texture if none was present, using the converted
  1285.     ** data.
  1286.     ** Otherwise, call W3D_UpdateTexImage
  1287.     */
  1288.  
  1289.     if (context->w3dTexBuffer[current] == NULL)
  1290.     {
  1291.     W3D_Texture *tex;
  1292.  
  1293.     AllocTags[0].ti_Tag  = W3D_ATO_IMAGE;
  1294.     AllocTags[0].ti_Data = (ULONG)context->w3dTexMemory[current];
  1295.  
  1296.     AllocTags[1].ti_Tag  = W3D_ATO_FORMAT;
  1297.     AllocTags[1].ti_Data = useFormat;
  1298.  
  1299.     AllocTags[2].ti_Tag  = W3D_ATO_WIDTH;
  1300.     AllocTags[2].ti_Data = w;
  1301.  
  1302.     AllocTags[3].ti_Tag  = W3D_ATO_HEIGHT;
  1303.     AllocTags[3].ti_Data = h;
  1304.  
  1305.     AllocTags[4].ti_Tag  = TAG_DONE;
  1306.     AllocTags[4].ti_Data = 0;
  1307.  
  1308.     tex = W3D_AllocTexObj(context->w3dContext, &error, AllocTags);
  1309.  
  1310.     if (tex == NULL || error != W3D_SUCCESS) return;
  1311.  
  1312.     context->w3dTexBuffer[current] = tex;
  1313.  
  1314.     /*
  1315.     ** Set the appropriate wrap modes, texture env, and filters
  1316.     */
  1317.  
  1318.     tex_SetWrap(context, context->WrapS, context->WrapT);
  1319.     tex_SetFilter(context, context->MinFilter, context->MagFilter);
  1320.     tex_SetEnv(context, context->TexEnv[0]);
  1321.  
  1322.     }
  1323.     else
  1324.     {
  1325. #ifndef __PPC__
  1326.         UpdateTexImage(context->w3dContext, context->w3dTexBuffer[current],
  1327.             context->w3dTexMemory[current], 0, NULL);
  1328. #else
  1329.         W3D_UpdateTexImage(context->w3dContext, context->w3dTexBuffer[current],
  1330.             context->w3dTexMemory[current], 0, NULL);
  1331. #endif
  1332.  
  1333.     }
  1334. }
  1335.  
  1336.  
  1337.  
  1338.  
  1339. //used for fast update when srcfmt = dstfmt :
  1340.  
  1341. #ifdef EIGHTBIT_TEXTURES
  1342.  
  1343. inline void tex_UpdateScanlineByte(UBYTE *start, UBYTE *pixels, int numpixels)
  1344. {
  1345.     int i;
  1346.  
  1347.     //update the 8-bit Alpha/Luminance Channel
  1348.     //fast copy
  1349.  
  1350.     UBYTE *in = (UBYTE*)pixels;
  1351.     UBYTE *out = (UBYTE*)start;
  1352.  
  1353.     for (i=0; i<numpixels; i++)
  1354.     {
  1355.         *out++ = *in++;
  1356.     }
  1357. }
  1358. #endif
  1359.  
  1360. inline void tex_UpdateScanlineShort(UWORD *start, UBYTE *pixels, int numpixels)
  1361. {
  1362.     int i;
  1363.  
  1364.     UWORD *in = (UWORD*)pixels;
  1365.     UWORD *out = (UWORD*)start;
  1366.  
  1367.     for (i=0; i<numpixels; i++)
  1368.     {
  1369.         *out++ = *in++;
  1370.     }
  1371. }
  1372.  
  1373. //Conversion:
  1374.  
  1375. inline void tex_UpdateScanlineA8_ARGB(UWORD *start, UBYTE *pixels, int numpixels)
  1376. {
  1377.     int i;
  1378.     UBYTE a;
  1379.  
  1380.     for (i=0; i<numpixels; i++)
  1381.     {
  1382.         a = *pixels++;
  1383.         *start++ = ( ((UWORD)a & 0xF0) << 8) | 0x0FFF;
  1384.     }
  1385. }
  1386.  
  1387. inline void tex_UpdateScanlineL8_ARGB(UWORD *start, UBYTE *pixels, int numpixels)
  1388. {
  1389.     int i;
  1390.     UBYTE la,lb,lc;
  1391.  
  1392.     for (i=0; i<numpixels; i++)
  1393.     {
  1394.         la = lb = lc = *pixels++;
  1395.         *start++ = ARGBFORM(0xff, la, lb, lc);
  1396.     }
  1397. }
  1398.  
  1399. inline void tex_UpdateScanlineAlpha(UWORD *start, UBYTE *pixels, int numpixels)
  1400. {
  1401.     int i;
  1402.     UBYTE r,g,b,a;
  1403.     for (i=0; i<numpixels; i++)
  1404.     {
  1405.         r=*pixels++;
  1406.         g=*pixels++;
  1407.         b=*pixels++;
  1408.         a=*pixels++;
  1409.  
  1410.         *start++ = ARGBFORM(a,r,g,b);
  1411.     }
  1412. }
  1413.  
  1414. inline void tex_UpdateScanlineNoAlpha(UWORD *start, UBYTE *pixels, int numpixels)
  1415. {
  1416.     int i;
  1417.     UBYTE r,g,b;
  1418.     for (i=0; i<numpixels; i++)
  1419.     {
  1420.         r=*pixels++;
  1421.         g=*pixels++;
  1422.         b=*pixels++;
  1423.  
  1424.         *start++ = RGBFORM(r,g,b);
  1425.     }
  1426. }
  1427.  
  1428. inline void tex_UpdateScanlineVerbatim(UBYTE *start, UBYTE *pixels, int numpixels)
  1429. {
  1430.     memcpy(pixels, start, numpixels);
  1431. }
  1432.  
  1433.  
  1434. void GLTexSubImage2DNoMIP(GLcontext context, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
  1435.  
  1436. void GLTexSubImage2D(GLcontext context, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
  1437. {
  1438.     int current;
  1439.  
  1440.     if (context->NoMipMapping == GL_TRUE)
  1441.     {
  1442.         GLTexSubImage2DNoMIP(context, target, level, xoffset, yoffset, width, height, format, type, (void *)pixels);
  1443.         return;
  1444.     }
  1445.  
  1446.     if(context->ActiveTexture)
  1447.         current = context->VirtualBinding;
  1448.     else
  1449.         current = context->CurrentBinding;
  1450.  
  1451.  
  1452.     GLFlagError(context, target!=GL_TEXTURE_2D, GL_INVALID_ENUM);
  1453.     GLFlagError(context, context->w3dTexBuffer[current] == NULL, GL_INVALID_OPERATION);
  1454.  
  1455. //    GLFlagError(context, 1, GL_INVALID_OPERATION);
  1456. }
  1457.  
  1458. void GLTexSubImage2DNoMIP(GLcontext context, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
  1459. {
  1460.     UBYTE *where;
  1461.     UBYTE *from = pixels;
  1462.     int current;
  1463.     int linelength;
  1464.     int sourcelength, sourceunit = 0;
  1465.     int i; 
  1466.     ULONG BytesPerTexel;
  1467.  
  1468.     if(context->ActiveTexture)
  1469.         current = context->VirtualBinding;
  1470.     else
  1471.         current = context->CurrentBinding;
  1472.  
  1473.     GLFlagError(context, target!=GL_TEXTURE_2D, GL_INVALID_ENUM);
  1474.  
  1475.     GLFlagError(context, context->w3dTexBuffer[context->CurrentBinding] == NULL, GL_INVALID_OPERATION);
  1476.  
  1477.     GLFlagError(context, type != GL_UNSIGNED_BYTE, GL_INVALID_ENUM);
  1478.  
  1479. #ifdef EIGHTBIT_TEXTURES
  1480.     if(format == GL_ALPHA || format == GL_LUMINANCE)
  1481.         BytesPerTexel = 1;
  1482.     else
  1483. #endif
  1484.         BytesPerTexel = context->w3dBytesPerTexel;
  1485.  
  1486.     switch(format)
  1487.     {
  1488.         case GL_ALPHA:
  1489.         case GL_LUMINANCE:
  1490.             sourceunit = 1;
  1491.         break;
  1492.  
  1493.         case GL_LUMINANCE_ALPHA:
  1494.         case MGL_UNSIGNED_SHORT_4_4_4_4:
  1495.         case MGL_UNSIGNED_SHORT_5_6_5:
  1496.             sourceunit = 2;
  1497.         break;
  1498.  
  1499.         case GL_RGBA:
  1500.         case 4:
  1501.             sourceunit = 4;
  1502.         break;
  1503.  
  1504.         case GL_RGB:
  1505.         case 3:
  1506.             sourceunit = 3;
  1507.         break;
  1508.  
  1509.     }
  1510.  
  1511.     linelength = context->w3dTexBuffer[current]->texwidth * BytesPerTexel;
  1512.  
  1513.     sourcelength = width * sourceunit;
  1514.  
  1515.     where = (UBYTE *)context->w3dTexMemory[current]
  1516.       +          linelength * yoffset
  1517.       +          BytesPerTexel * xoffset;
  1518.  
  1519. #ifdef EIGHTBIT_TEXTURES
  1520.     if(format == GL_ALPHA || format == GL_LUMINANCE)
  1521.     {
  1522.         for (i=0; i<height; i++)
  1523.         {
  1524.             tex_UpdateScanlineByte(where, from, width);
  1525.             where += linelength;
  1526.             from  += sourcelength;
  1527.         }
  1528.     }
  1529.     else
  1530. #endif
  1531.     if(context->w3dTexBuffer[current]->texfmtsrc == W3D_L8A8)
  1532.     {
  1533.         for (i=0; i<height; i++)
  1534.         {
  1535.             tex_UpdateScanlineShort((UWORD *)where, from, width);
  1536.             where += linelength;
  1537.             from  += sourcelength;
  1538.         }
  1539.     }
  1540.     else if (context->w3dTexBuffer[current]->texfmtsrc == context->w3dFormat)
  1541.     {
  1542.        if(sourceunit == 2)
  1543.        {
  1544.         for (i=0; i<height; i++)
  1545.         {
  1546.             tex_UpdateScanlineShort((UWORD *)where, from, width);
  1547.             where += linelength;
  1548.             from  += sourcelength;
  1549.         }
  1550.        }
  1551.        else
  1552.        {
  1553.         for (i=0; i<height; i++)
  1554.         {
  1555.             tex_UpdateScanlineNoAlpha((UWORD *)where, from, width);
  1556.             where += linelength;
  1557.             from  += sourcelength;
  1558.         }
  1559.        }
  1560.     }
  1561. #ifndef EIGHTBIT_TEXTURES
  1562.     else if (format == GL_ALPHA)
  1563.     {
  1564.         for (i=0; i<height; i++)
  1565.         {
  1566.             tex_UpdateScanlineA8_ARGB((UWORD *)where, from, width);
  1567.             where += linelength;
  1568.             from  += sourcelength;
  1569.         }
  1570.  
  1571.     }
  1572.     else if (format == GL_LUMINANCE)
  1573.     {
  1574.         for (i=0; i<height; i++)
  1575.         {
  1576.             tex_UpdateScanlineL8_ARGB((UWORD *)where, from, width);
  1577.             where += linelength;
  1578.             from  += sourcelength;
  1579.         }
  1580.  
  1581.     }
  1582. #endif
  1583.     else if (context->w3dTexBuffer[current]->texfmtsrc == context->w3dAlphaFormat)
  1584.     {
  1585.        if(sourceunit == 2)
  1586.        {
  1587.         for (i=0; i<height; i++)
  1588.         {
  1589.             tex_UpdateScanlineShort((UWORD *)where, from, width);
  1590.             where += linelength;
  1591.             from  += sourcelength;
  1592.         }
  1593.        }
  1594.        else
  1595.        {
  1596.         for (i=0; i<height; i++)
  1597.         {
  1598.             tex_UpdateScanlineAlpha((UWORD *)where, from, width);
  1599.             where += linelength;
  1600.             from  += sourcelength;
  1601.         }
  1602.        }
  1603.     }
  1604.     else
  1605.     {
  1606.         for (i=0; i<height; i++)
  1607.         {
  1608.             tex_UpdateScanlineVerbatim((UBYTE *)where, from, width);
  1609.             where += linelength;
  1610.             from  += sourcelength;
  1611.         }
  1612.     }
  1613.  
  1614. //experimental shortcut
  1615. /*
  1616.     if(context->w3dContext->CurrentChip == W3D_CHIP_AVENGER_BE)
  1617.     {
  1618.        context->w3dTexBuffer[current]->dirty = W3D_TRUE;
  1619.     }
  1620.     else
  1621.     {
  1622. */
  1623.     #ifndef __PPC__
  1624.  
  1625.     UpdateTexImage(context->w3dContext, context->w3dTexBuffer[current],
  1626.         context->w3dTexMemory[current], 0, NULL);
  1627.     #else
  1628.  
  1629.     W3D_UpdateTexImage(context->w3dContext, context->w3dTexBuffer[current],
  1630.         context->w3dTexMemory[current], 0, NULL);
  1631.  
  1632.     #endif
  1633. /*
  1634.     }
  1635. */
  1636. }
  1637.  
  1638. void GLTexGeni(GLcontext context, GLenum coord, GLenum mode, GLenum map)
  1639. {
  1640. //    GLFlagError(context, 1, GL_INVALID_OPERATION);
  1641. }
  1642.  
  1643. void GLColorTable(GLcontext context, GLenum target, GLenum internalformat, GLint width, GLenum format, GLenum type, GLvoid *data)
  1644. {
  1645.     int i;
  1646.     GLubyte *palette;
  1647.     GLubyte *where;
  1648.     GLubyte a,r,g,b;
  1649.  
  1650.     GLFlagError(context, width>256, GL_INVALID_VALUE);
  1651.     GLFlagError(context, target!=GL_COLOR_TABLE, GL_INVALID_OPERATION);
  1652.  
  1653.     palette = (GLubyte *)data;
  1654.     where   = (GLubyte *)context->PaletteData;
  1655.  
  1656.     GLFlagError(context, where == NULL, GL_INVALID_OPERATION);
  1657.  
  1658.     switch(internalformat)
  1659.     {
  1660.         case 4:
  1661.         case GL_RGBA: // convert to argb from...
  1662.             switch(format)
  1663.             {
  1664.                 case GL_RGB: // ...RGB, ignoring alpha
  1665.                     for (i=0; i<width; i++)
  1666.                     {
  1667.                         r=*palette++;
  1668.                         g=*palette++;
  1669.                         b=*palette++;
  1670.                         palette++;
  1671.                         *where++ = r;
  1672.                         *where++ = g;
  1673.                         *where++ = b;
  1674.                     }
  1675.                     break;
  1676.                 case GL_RGBA: // ...ARGB with alpha
  1677.                     for (i=0; i<width; i++)
  1678.                     {
  1679.                         a=*palette++;
  1680.                         r=*palette++;
  1681.                         g=*palette++;
  1682.                         b=*palette++;
  1683.                         *where++ = a;
  1684.                         *where++ = r;
  1685.                         *where++ = g;
  1686.                         *where++ = b;
  1687.                     }
  1688.                     break;
  1689.             }
  1690.             break;
  1691.         case 3:
  1692.         case GL_RGB: // convert to RGB from...
  1693.             switch(format)
  1694.             {
  1695.                 case GL_RGB: // ...RGB without alpha
  1696.                     for (i=0; i<width; i++)
  1697.                     {
  1698.                         r=*palette++;
  1699.                         g=*palette++;
  1700.                         b=*palette++;
  1701.                         *where++ = r;
  1702.                         *where++ = g;
  1703.                         *where++ = b;
  1704.                     }
  1705.                     break;
  1706.                 case GL_RGBA: // ...ARGB, assuming alpha == 1
  1707.                     for (i=0; i<width; i++)
  1708.                     {
  1709.                         r=*palette++;
  1710.                         g=*palette++;
  1711.                         b=*palette++;
  1712.                         *where++ = 0xff;
  1713.                         *where++ = r;
  1714.                         *where++ = g;
  1715.                         *where++ = b;
  1716.                     }
  1717.                     break;
  1718.             }
  1719.             break;
  1720.     }
  1721.     context->PaletteFormat = format;
  1722.     context->PaletteSize   = width;
  1723. }
  1724.  
  1725.  
  1726.  
  1727. void GLActiveTextureARB(GLcontext context, GLenum unit)
  1728. {
  1729.     GLFlagError(context, (unit < GL_TEXTURE0_ARB || unit > (GL_TEXTURE0_ARB+MAX_TEXUNIT)), GL_INVALID_ENUM);
  1730.  
  1731.     context->ActiveTexture = unit - GL_TEXTURE0_ARB;
  1732. }
  1733.